package com.inspur.edp.formserver.vmmanager.service;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.inspur.edp.cef.designtime.api.IGspCommonField;
import com.inspur.edp.cef.designtime.api.util.MetadataUtil;
import com.inspur.edp.formserver.viewmodel.GspViewModelElement;
import com.inspur.edp.formserver.viewmodel.exception.ViewModelException;
import com.inspur.edp.formserver.viewmodel.json.element.ViewElementDeserializer;
import com.inspur.edp.formserver.viewmodel.json.element.ViewElementSerializer;
import com.inspur.edp.formserver.viewmodel.util.UpdateVoElementUtil;
import com.inspur.edp.formserver.vmmanager.exception.VoManagerErrorCodes;
import com.inspur.edp.lcm.metadata.api.IMetadataContent;
import com.inspur.edp.lcm.metadata.api.entity.GspMetadata;
import com.inspur.edp.lcm.metadata.api.service.RefCommonService;
import com.inspur.edp.udt.designtime.api.entity.UnifiedDataTypeDef;
import io.iec.edp.caf.commons.utils.SpringBeanUtils;

public class UpdateVirtualVoElementWithUdtService {
    private String errorCode = "UpdateVirtualVoWithUdtService";

    public static UpdateVirtualVoElementWithUdtService getInstance() {
        return new UpdateVirtualVoElementWithUdtService();
    }

    /// <summary>
    /// 根据选中的udt元数据,更新多值udt字段信息
    /// 更新ChildElements,Mapping
    /// 说明：若为字段上选择udt，所有属性带出；若为加载更新，则仅更新使用方式为【约束】的属性。
    /// </summary>
    /// <returns>更新后字段的json序列化</returns>
    public String UpdateVariableWithRefUdt(String refUdtId, String path, String udtElementJson, boolean isFirstChoose) {
        RefCommonService metadataService = SpringBeanUtils.getBean(RefCommonService.class);

        GspMetadata refUdtMetadata = metadataService.getRefMetadata(refUdtId);
        return UpdateVariable(refUdtMetadata, udtElementJson, isFirstChoose);
    }

    public String UpdateVariableWithRefUdt(JsonNode node, String refUdtId, String path, String udtElementJson, boolean isFirstChoose) {
//    RefCommonService metadataService = SpringBeanUtils.getBean(RefCommonService.class);
        GspMetadata refUdtMetadata = WebControllerService.getMetadata(node, path, "", refUdtId);
        return UpdateVariable(refUdtMetadata, udtElementJson, isFirstChoose);
    }

    /**
     * 运行时选择选中的udt元数据，更新udt信息
     *
     * @param refUdtId
     * @param path
     * @param udtElementJson
     * @param isFirstChoose
     * @return
     */
    public String UpdateVariableWithRefUdtRT(String refUdtId, String path, String udtElementJson, boolean isFirstChoose) {
        GspMetadata refUdtMetadata = MetadataUtil.getCustomMetadata(refUdtId);
        return UpdateVariable(refUdtMetadata, udtElementJson, isFirstChoose);
    }

    public String UpdateVariable(GspMetadata refUdtMetadata, String udtElementJson, boolean isFirstChoose) {
        GspViewModelElement element;
        try {
            element = getMapper().readValue(udtElementJson, GspViewModelElement.class);
        } catch (JsonProcessingException e) {
            throw new ViewModelException(VoManagerErrorCodes.GSP_VIEWOBJECT_MANAGER_0044, e);
        }
        IMetadataContent content = refUdtMetadata.getContent();
        if (content instanceof UnifiedDataTypeDef) {
            UpdateVoElementUtil util = new UpdateVoElementUtil();
            util.UpdateElementWithRefUdt(element, (UnifiedDataTypeDef) content, isFirstChoose);
        } else {
            throw new ViewModelException(VoManagerErrorCodes.GSP_VIEWOBJECT_MANAGER_0042, null);
        }
        String eleJson;
        try {
            eleJson = getMapper().writeValueAsString(element);
        } catch (JsonProcessingException e) {
            throw new ViewModelException(VoManagerErrorCodes.GSP_VIEWOBJECT_MANAGER_0045, e);
        }
        return eleJson;
    }

    private ObjectMapper getMapper() {

        ObjectMapper mapper = new ObjectMapper();
        SimpleModule module = new SimpleModule();
        module.addDeserializer(IGspCommonField.class, new ViewElementDeserializer());
        module.addSerializer(IGspCommonField.class, new ViewElementSerializer());
        mapper.registerModule(module);
        return mapper;
    }
}
